package main

import (
	"encoding/json"
	"flag"
	"fmt"
	uuid "github.com/satori/go.uuid"
	"io"
	"lesson1/blockchain"
	"lesson1/parse"
	"log"
	"net/http"
	"strings"
)


func main()  {
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		uidBytes, err := uuid.NewV4()
		if err != nil {
			log.Panic(err)
		}
		uid := strings.ReplaceAll(uidBytes.String(), "-", "")

		writer.Write([]byte(uid))
	})

	//post 请求， 新建交易
	http.HandleFunc("/transaction", func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != http.MethodPost {
			writer.WriteHeader(403)
			writer.Write([]byte("请求方式不正确"))
			return
		}

		defer request.Body.Close()
		bytes, err := io.ReadAll(request.Body)
		if err != nil {
			writer.WriteHeader(400)
			fmt.Fprintln(writer, err.Error())
			return
		}
		var t blockchain.Transaction
		json.Unmarshal(bytes, &t)
		if !parse.VerifyTransaction(t) {
			writer.WriteHeader(400)
			fmt.Fprintln(writer, "参数不全")
			return
		}
		blockchain.AddTransaction(t)
		writer.Write(parse.RespOk(0, nil, "创建交易成功"))
	})
	//get 请求， 挖矿
	http.HandleFunc("/mine", func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != http.MethodGet {
			writer.WriteHeader(403)
			writer.Write([]byte("请求方式不正确"))
			return
		}

		request.ParseForm()
		recipient := request.URL.Query().Get("recipient")

		chain := blockchain.LastBlockChain()
		lastProof := chain.WorkProof
		currentProof := blockchain.WorkProof(lastProof)
		blockchain.NewTransaction("0", recipient, 1)
		currentChain := blockchain.NewBlockChain(currentProof, "")
		respBytes := parse.RespOk(0, currentChain, "挖矿成功")
		writer.Write(respBytes)
	})
	//get 请求， 列出所有的区块链
	http.HandleFunc("/blockChains", func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != http.MethodGet {
			writer.WriteHeader(403)
			writer.Write([]byte("请求方式不正确"))
			return
		}
		bytes, err := json.Marshal(blockchain.FullBlockChains{
			BlockChains: blockchain.BlockChains,
			Length: len(blockchain.BlockChains),
		})
		if err != nil {
			fmt.Fprintln(writer, err.Error())
			return
		}

		writer.Write(bytes)
	})
	http.HandleFunc("/node/register", func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != http.MethodPost {
			writer.WriteHeader(403)
			writer.Write([]byte("请求方式不正确"))
			return
		}

		body := request.Body
		defer body.Close()

		contentBytes, err := io.ReadAll(body)
		if err != nil {
			log.Println(err)
			fmt.Fprintln(writer, err.Error())
			return
		}
		if len(contentBytes) <= 0 {
			writer.Write([]byte("请求参数不存在"))
			return
		}
		nodesParams := make([]parse.RNodesParams, 0)
		json.Unmarshal(contentBytes, &nodesParams)

		for _, nodesParam := range nodesParams {
			blockchain.RegisterNode(nodesParam.Url)
		}

		data := parse.RespOk(0, blockchain.Nodes, "节点注册成功过")
		writer.Write(data)
	})

	http.HandleFunc("/node/resolve", func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != http.MethodGet {
			writer.WriteHeader(403)
			writer.Write([]byte("请求方式不正确"))
		}
		replace := blockchain.ResolveConflictFromNodes()
		msg := "我们的区块链才是最权威的区块链"
		if replace {
			msg = "我们的区块链已经被换了"
		}

		respData := parse.RespOk(0, blockchain.BlockChains, msg)

		writer.Write(respData)
	})

	port := "5000"
	flag.StringVar(&port, "port", port, "port")
	flag.Parse()

	err := http.ListenAndServe(":" + port, nil)
	if err != nil {
		log.Panic(err)
		return
	}
}
